/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package E_implicito_Brent;

/**
 *
 * @author emanuelle
 */
public class TabelaHash {

    private int tamanhoTabela;
    private Celula celulas[];

    public TabelaHash(int tamanho){
        celulas = new Celula[tamanho];
        this.tamanhoTabela = tamanho;
        for(int i = 0; i < tamanho; i++){ //Preenche a tabela com as células de acordo com o tamanho da tabela hash
            celulas[i] = new Celula(i);
        }
    }

    public Celula getCelula(int posicao){
        return celulas[posicao];
    }

    private int getIndex(int chave){
        return chave % tamanhoTabela;
    }

    public int insertion(int chave){
        Record record = new Record(chave);
        int index = getIndex(chave);
        if(celulas[index].insertRecord(record)){ /*******Tenta inserir na posição**********/
            return 0;
        }
        else{ /*****Caso a posicao esteja ocupada*******/
            int index2 = getIndex(chave/tamanhoTabela); /*Pega o valor do segundo HASH da chave*/
            if(index2 == 0){
                index2 = 1;
            }
            int auxIndex = index; /*Variável auxiliar*/
            int acessoInserido = 1;/*Quantidade de acessos do elemento inserido, sem empurrao*/
            while(celulas[auxIndex].getRecord()!=null){ /*Calculo da quantidade de acessos sem empurrão*/
                acessoInserido++;
                auxIndex = auxIndex + index2;
                auxIndex = getIndex(auxIndex);
            }
            for(int i=2; i<acessoInserido; i++){ /*Calculo do empurrao com menos acessos*/
                int ins = 1; /*Quantidade de acessos do elemento inserido*/
                int emp = i - ins; /*Quantidade de acessos do elemento empurrado alem da posição*/
                int auxIndex1 = index;
                int auxIndex2 = index;
                int index3 = 1;
                while(ins < i){
                    auxIndex1 = index + (ins-1)*index2;
                    auxIndex1 = getIndex(auxIndex1);
                    index3 = getIndex(celulas[auxIndex1].getRecord().getChave()/tamanhoTabela);
                    if(index3 == 0){
                        index3 = 1;
                    }
                    auxIndex2 = auxIndex1 + emp*index3;
                    auxIndex2 = getIndex(auxIndex2);
                    if(celulas[auxIndex2].getRecord()==null){
                        Record auxRecord = celulas[auxIndex1].getRecord();
                        celulas[auxIndex1].setRecord(record);
                        celulas[auxIndex2].insertRecord(auxRecord);
                        return 1;
                    }else{
                        ins++;
                        emp = i - ins;
                    }
                }
            }
            celulas[auxIndex].insertRecord(record);
            return 1;
        }
    }

    public int search(int chave){
        int index = getIndex(chave);
        int acessos = 1;
        int index2 = getIndex(chave/tamanhoTabela);
        if(index2 == 0){
            index2 = 1;
        }
        while(!celulas[index].searchRecord(chave)){
            index = index + index2;
            index = getIndex(index);
            acessos++;
        }
        return acessos;

    }

}
